<?php 

class GencodedocCommand extends CConsoleCommand
{
	
	public
		$root,
		$active_plugins = array(),
		$wo_plugins = false,
		$output_encoding = 'windows-1251',
		$input_encoding = 'utf-8'
	;
	
	public function getClassByPath($path){
		if(!preg_match('#/([^/]+)/\1\.class\.php$#i', $path)){
			return false;
		}
		$path = str_replace($this->root.'/', '', $path);
		$epath = preg_split('#/+#', $path, -1, PREG_SPLIT_NO_EMPTY);
		switch($epath[0]){
			case 'plugins':
				if(!in_array($epath[1], $this->active_plugins)){
					return;
				}
				return 'Plugin'.ucfirst($epath[1]).'_Module'.ucfirst($epath['4']);
				break;
			default:
				return 'Module'.ucfirst($epath[2]);
		}
	}
	
	/**
	 * Execute the action.
	 * @param array command line parameters specific for this command
	 */
	public function run($args)
	{
		
		$this->wo_plugins = in_array('wop',$args);
		
		$e = Yii::E();
		
		$this->root = Config::Get('path.root.server');
		
		
		if(!$this->wo_plugins)
			$this->active_plugins = $e->Plugin_GetActivePlugins();
		
		$engine_module_files = glob($this->root.'/engine/modules/*/*.class.php');
		$core_module_files = glob($this->root.'/classes/modules/*/*.class.php');
		$plugin_module_files = $this->active_plugins && !$this->wo_plugins
			? glob($this->root.'/plugins/*/classes/modules/*/*.class.php', GLOB_BRACE)
			: array()
		;
		$module_files = array_merge($engine_module_files, $core_module_files, $plugin_module_files);
		
		$module_classes = array_filter(
			array_map(array($this,'getClassByPath'), $module_files)
		);
		
		$need_inherits = $unique_firsts = array();
		
		foreach($module_classes as $module_class){
			$first_class = $e->Plugin_GetDelegater('module', $module_class);
			$last_class = $e->Plugin_GetDelegate('module', $first_class);
			if($first_class != $last_class){
				$need_inherits[strtolower($first_class)] = array($first_class,$last_class);
			}
			$unique_firsts[strtolower($first_class)] = array($first_class,$last_class);
		}
		
		// inherit classes
		ob_start();
		echo "<?php\r\n";
		foreach($need_inherits as $classes){
			list($first_class, $last_class) = $classes;
			$rclass = new ReflectionClass($this->wo_plugins?$first_class:$last_class);
			
			do{
				$rpclass = $rclass->getParentClass();
				//var_dump($rpclass->getName());
				if(LsClassInfo::GetClassInfo($rpclass->getName(), LsClassInfo::CI_INHERIT, true)){
					echo "abstract class {$rpclass->getName()} extends $first_class {}\r\n";
				}
				$rclass = $rpclass;
			}while($rpclass->getName() != 'Object');
		}
		$content = ob_get_clean();
		file_put_contents($f = $this->root.'/codedoc/inherits.php_', $content);
		@unlink(rtrim($f,'_'));
		rename($f,rtrim($f,'_'));
		
		
		// magic methods
		ob_start();
		echo "<?php abstract class Object {";
		
		foreach($unique_firsts as $classes){
			list($first_class, $last_class) = $classes;
			
			//var_dump($class);
			
			$pprefix = LsClassInfo::GetClassInfo($first_class, LsClassInfo::CI_PPREFIX, true);
			$mprefix = $pprefix.LsClassInfo::GetClassInfo($first_class, LsClassInfo::CI_MODULE, true).'_';
			
			$rclass = new ReflectionClass($this->wo_plugins?$first_class:$last_class);
			$rmethods = $rclass->getMethods();
			
			
			foreach ($rmethods as $rmethod){
				if(!$rmethod->isPublic() || $rmethod->isStatic()
				|| preg_match('#^__#', $rmethod->getName())){
					continue;
				}
				
				$rparams = $rmethod->getParameters();
				$rargs = $rargsCall = array();
				foreach ($rparams as $rparam){
					$rargsCall[] = '$'.$rparam->getName();
					if($rparam->isDefaultValueAvailable()){
						$defval = '='.var_export($rparam->getDefaultValue(),true);
						if($defval == '=-INF'){
							$defval = '';
						}
					}
					$rargs[] =
						 ($rparam->isPassedByReference() ? '&' : '')
						.'$'.$rparam->getName()
						.($rparam->isDefaultValueAvailable() ? $defval : '')
					;
				}
				$doc = $rmethod->getDocComment();
				$see_tag = "@see {$rmethod->getDeclaringClass()->getName()}::{$rmethod->getName()}()\r\n"
					."\t * @link file:///{$rmethod->getFileName()} {$rmethod->getDeclaringClass()->getName()}::{$rmethod->getName()} declaration" //#L{$rmethod->getStartLine()}
				;
				// why @link is not visible in popup and @see is not a link? 
				if($doc){
					$doc = str_replace('*/', "* {$see_tag}\r\n\t */", $doc);
				}else{
					$doc = "/**\r\n\t *\r\n\t * {$see_tag}\r\n \t */";
				}
				echo iconv(
					$this->input_encoding,
					$this->output_encoding,
					"\r\n\t{$doc}\r\n\tpublic function {$mprefix}{$rmethod->getName()}(".join(', ', $rargs)."){ }\r\n"
				);
			}
			
		}
		echo "}";
		$content = ob_get_clean();
		file_put_contents($f = $this->root.'/codedoc/methods.php_', $content);
		@unlink(rtrim($f,'_'));
		rename($f,rtrim($f,'_'));
		
		if(in_array('end', $args)){
			exit;
		}
		
	}

}

?>